package com.ruoyi.system.service.impl;

import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.dto.SysIdleBoatInfoDto;
import com.ruoyi.common.core.domain.entity.system.*;
import com.ruoyi.common.enums.BoatStatus;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.mapper.SysBoatMapper;
import com.ruoyi.system.mapper.SysPintuanParentOrderMapper;
import com.ruoyi.system.mapper.UserBoatOrderInfoMapper;
import com.ruoyi.system.service.ISysBoatService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 船只信息Service业务层处理
 *
 * @author zjw
 * @date 2023-06-21
 */
@Service
public class SysBoatServiceImpl implements ISysBoatService {
    @Resource
    private SysBoatMapper sysBoatMapper;

    @Resource
    private UserBoatOrderInfoMapper userBoatOrderInfoMapper;

    @Resource
    private SysPintuanParentOrderMapper sysPintuanParentOrderMapper;

    /**
     * 查询船只信息
     *
     * @param boatId 船只信息主键
     * @return 船只信息
     */
    @Override
    public SysBoat selectSysBoatByBoatId(Long boatId) {
        SysBoat sysBoat = sysBoatMapper.selectSysBoatByBoatId(boatId);
        if (Objects.nonNull(sysBoat)) {
            Long[] shiplineIds = sysBoat.getShiplines().stream().filter(sysShipline -> Objects.nonNull(sysShipline.getShiplineId()) && StringUtils.isNotEmpty(sysShipline.getCoordinates()))
                    .map(SysShipline::getShiplineId).toArray(Long[]::new);
            sysBoat.setShiplineIds(shiplineIds);
        }

        return sysBoat;
    }

    @Override
    public SysBoat selectSysBoatByBoatIdentityId(String boatIdentityId) {
        SysBoat sysBoat = sysBoatMapper.selectSysBoatByBoatIdentityId(boatIdentityId);
        if (Objects.nonNull(sysBoat)) {
            Long[] shiplineIds = sysBoat.getShiplines().stream().filter(sysShipline -> Objects.nonNull(sysShipline.getShiplineId()) && StringUtils.isNotEmpty(sysShipline.getCoordinates()))
                    .map(SysShipline::getShiplineId).toArray(Long[]::new);
            sysBoat.setShiplineIds(shiplineIds);
        }

        return sysBoat;
    }

    /**
     * 查询船只信息列表
     *
     * @param sysBoat 船只信息
     * @return 船只信息
     */
    @Override
//    @DataScope(userAlias = "u", scenicAlias = "s")
    public List<SysBoat> selectSysBoatList(SysBoat sysBoat) {
        List<SysBoat> boatList = sysBoatMapper.selectSysBoatList(sysBoat);
        return boatList;
    }

    /**
     * 新增船只信息
     *
     * @param sysBoat 船只信息
     * @return 结果
     */
    @Override
    public int insertSysBoat(SysBoat sysBoat) {
        sysBoat.setCreateTime(DateUtils.getNowDate());
        return sysBoatMapper.insertSysBoat(sysBoat);
    }

    /**
     * 修改船只信息
     *
     * @param sysBoat 船只信息
     * @return 结果
     */
    @Override
    public int updateSysBoat(SysBoat sysBoat) {
        Long boatId = sysBoat.getBoatId();
        return sysBoatMapper.updateSysBoat(sysBoat);
    }

    /**
     * 更新船只的位置及方位信息。
     *
     * @param boatId
     * @param lon
     * @param lat
     * @param orientation
     */
    @Override
    public void updateBoatLocationInfo(Long boatId, Double lon, Double lat, Integer orientation) {
        sysBoatMapper.updateBoatLocationInfo(boatId, lon, lat, orientation);
    }

    @Override
    public int updateBoatStatusByBoadId(Long boatId, BoatStatus boatStatus) {
        int result = sysBoatMapper.updateBoatStatusByBoadId(boatId, boatStatus.getCode(), boatStatus.getInfo(), DateUtils.getNowDate());
        return result;
    }

    /**
     * 批量删除船只信息
     *
     * @param boatIds 需要删除的船只信息主键
     * @return 结果
     */
    @Override
    public int deleteSysBoatByBoatIds(Long[] boatIds) {
        return sysBoatMapper.deleteSysBoatByBoatIds(boatIds);
    }

    /**
     * 删除船只信息信息
     *
     * @param boatId 船只信息主键
     * @return 结果
     */
    @Override
    public int deleteSysBoatByBoatId(Long boatId) {
        return sysBoatMapper.deleteSysBoatByBoatId(boatId);
    }

    @Override
    public List<SysIdleBoatInfoDto> selectAllIdleSysBoat(Long scenicId, Long wharfId) {
        List<SysBoat> sysBoats = sysBoatMapper.selectAllIdleSysBoatByScenicIdAndWharfId(scenicId, wharfId);
        List<SysIdleBoatInfoDto> sysIdleBoatInfoDtos = sysBoats.stream().map(sysBoat -> {
            SysIdleBoatInfoDto sysIdleBoatInfoDto = new SysIdleBoatInfoDto();
            BeanUtils.copyProperties(sysBoat, sysIdleBoatInfoDto);
            return sysIdleBoatInfoDto;
        }).collect(Collectors.toList());
        return sysIdleBoatInfoDtos;
    }

    @Override
    public List<Map<String, Object>> getAllIdleAndGroupbookingBoatList(Long scenicId, Long wharfId, Long pintuanId) {
        List<Map<String, Object>> resultList = new ArrayList<>();

        //先获取指定景区下指定码头中所有正处于拼团中的船只列表。
        List<SysBoat> allGroupbookingBoatList = sysBoatMapper.getAllGroupbookingBoatList(scenicId, wharfId);
        if (Objects.nonNull(allGroupbookingBoatList) && allGroupbookingBoatList.size() > 0) {
            allGroupbookingBoatList.forEach(sysBoat -> {
                Long boatId = sysBoat.getBoatId();
                long expireTime = CacheUtils.getExpire(CacheConstants.Pintuan_Order_Redis_Key, String.valueOf(boatId));
                UserBoatOrderInfo userBoatOrderInfo = userBoatOrderInfoMapper.selectBoatOrderInfoByBoatId(boatId);
                SysPintuanParentOrder sysPintuanParentOrder = sysPintuanParentOrderMapper.selectSysPintuanParentOrderByOrderId(userBoatOrderInfo.getOrderId());
                List<SysPintuanChildrenOrder> pintuanChildrenOrderList = sysPintuanParentOrder.getPintuanChildrenOrderList();

                Map<String, Object> boatInfoMap = wrapperBoatInfo(sysBoat);
                boatInfoMap.put("pintuanId", pintuanId);
                boatInfoMap.put("pintuanRemainTime", expireTime); //设置拼团倒计时剩余时间，单位：秒。

                List<Map<String, Object>> userInfoMapList = new ArrayList<>();
                for (SysPintuanChildrenOrder childrenOrder : pintuanChildrenOrderList) {
                    Map<String, Object> userInfoMap = new HashMap<>();
                    userInfoMap.put("userId", childrenOrder.getUserId());
                    userInfoMap.put("profileIcon", "");
                    userInfoMapList.add(userInfoMap);
                }
                boatInfoMap.put("userList", userInfoMapList);

                resultList.add(boatInfoMap);
            });
        }

        //再获取指定景区下指定码头中所有空闲的船只。
        List<SysBoat> sysBoats = sysBoatMapper.selectAllIdleSysBoatByScenicIdAndWharfId(scenicId, wharfId);
        if (Objects.nonNull(sysBoats) && sysBoats.size() > 0) {
            sysBoats.forEach(sysBoat -> {
                Map<String, Object> boatInfoMap = wrapperBoatInfo(sysBoat);
                boatInfoMap.put("pintuanId", pintuanId);
                boatInfoMap.put("pintuanRemainTime", 0); //设置拼团倒计时剩余时间为0，表示当前此船只未处于拼团中。
                List<Map<String, Object>> userInfoMapList = new ArrayList<>();
                boatInfoMap.put("userList", userInfoMapList);

                resultList.add(boatInfoMap);
            });
        }
        return resultList;
    }

    @Override
    public List<SysBoat> getBoatListByScenicId(Long scenicId) {
        return sysBoatMapper.getBoatListByScenicId(scenicId);
    }

    @Override
    public void updateAllBoatStatus(BoatStatus boatStatus) {
        int boatStatusCode = boatStatus.getCode();
        String boatStatusInfo = boatStatus.getInfo();
        sysBoatMapper.updateAllBoatStatus(boatStatusCode, boatStatusInfo);
    }

    private Map<String, Object> wrapperBoatInfo(SysBoat sysBoat) {
        Map<String, Object> boatInfoMap = new HashMap<>();
        boatInfoMap.put("boatId", sysBoat.getBoatId());
        boatInfoMap.put("boatIdentityId", sysBoat.getBoatIdentityId());
        boatInfoMap.put("boatName", sysBoat.getBoatName());
        boatInfoMap.put("boatCode", sysBoat.getBoatCode());
        boatInfoMap.put("scenicId", sysBoat.getScenicId());
        boatInfoMap.put("wharfId", sysBoat.getWharfId());
        boatInfoMap.put("status", sysBoat.getStatus());
        boatInfoMap.put("statusDesc", sysBoat.getStatusDesc());

        return boatInfoMap;
    }
}
